package com.mediocre.service.impl;

import com.mediocre.service.IPostService;
import com.mediocre.util.BizUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Service
@Slf4j
public class PostService implements IPostService {

    @Value("${cnblogs.host}")
    private String host;
    @Value("${cnblogs.posts.query.uri}")
    private String queryUri;
    @Value("${cnblogs.posts.delete.uri}")
    private String deleteUri;
    @Value("${cnblogs.posts.delete_perm.uri}")
    private String deletePermUri;
    @Value("${cnblogs.posts.create_update.uri}")
    private String createOrUpdateUri;

    /**
     * 根据条件查询随笔记录
     * @param p 第几页，如为空，则设为默认值1，必须为整型
     * @param cid 分类id，一般为""
     * @param tid 标签id，一般为""
     * @param t postType，文章类型：1 随笔；2 文章；3 日记。一般为"1"
     * @param cfg 一般为"0"
     * @param search 筛选随笔内容，若为空，表示不筛选
     * @param s 每页显示条数，如为空，则设为默认值10，也必须为整型，且只能在1（含）到100（含）的范围内取值，
     *          如果超出每页显示条数，即超过100，则返回错误消息： {"errors":["请求每页条数超出范围"],"type":0}
     * @return 查询结果，json字符串
     */
    @Override
    public String list(String p, String cid, String tid, String t, String cfg, String search, String s) {
        if (!StringUtils.hasText(p)) p = "1";
        if (!StringUtils.hasText(cid)) cid = "";
        if (!StringUtils.hasText(tid)) tid = "";
        if (!StringUtils.hasText(t)) t = "1";
        if (!StringUtils.hasText(cfg)) cfg = "0";
        if (!StringUtils.hasText(s)) s = "10";
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        try {
            // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
            httpClient = HttpClientBuilder.create().build();

            // assemble url
            // eg. https://i.cnblogs.com/api/posts/list?p=1&cid=&tid=&t=1&cfg=0&search=pr&s=10
            StringBuilder url = new StringBuilder(host).append(queryUri)
                    .append("?p=").append(p)
                    .append("&cid=").append(cid)
                    .append("&tid=").append(tid)
                    .append("&t=").append(t)
                    .append("&cfg=").append(cfg)
                    .append("&search=").append(search)
                    .append("&s=").append(s);
            log.info("url === {}", url);

            // create request
            HttpGet httpGet = new HttpGet(url.toString());
            // 配置信息
            BizUtils.configRequest(httpGet);

            // 由客户端执行(发送)请求
            httpResponse = httpClient.execute(httpGet);
            log.info("response status -> {}", httpResponse.getStatusLine());
            // 获取并返回响应内容
            return BizUtils.getResponseStr(httpResponse);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // close resources
            BizUtils.closeResources(httpResponse, httpClient);
        }
        return null;
    }

    @Override
    public String list(String p, String s, String search) {
        // 参数中，一般cid="", tid="", t="1", cfg="0", search为空，表示不筛选文章内容
        return list(p, "", "", "1", "0", search, s);
    }

    @Override
    public String list(String p, String s) {
        // 参数中，一般cid="", tid="", t="1", cfg="0", search为空，表示不筛选文章内容
        return list(p, "", "", "1", "0", "", s);
    }

    @Override
    public String delete(String id) {
        if (!StringUtils.hasText(id)) return null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        try {
            // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
            httpClient = HttpClientBuilder.create().build();
            // assemble url
            // eg. https://i.cnblogs.com/api/posts/15155337
            StringBuilder url = new StringBuilder(host).append(deleteUri).append(id);
            log.info("url === {}", url);
            // create request
            HttpDelete httpDelete = new HttpDelete(url.toString());
            // 配置信息
            BizUtils.configRequest(httpDelete);
            // 由客户端执行(发送)请求
            httpResponse = httpClient.execute(httpDelete);
            // 获取并返回响应内容
            return BizUtils.getResponseStr(httpResponse);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // close resources
            BizUtils.closeResources(httpResponse, httpClient);
        }
        return null;
    }

    /**
     * 发布或更新随笔
     * 一分钟内只能发布3篇随笔，否则报错，如下：
     * 2021-08-23 21:41:03.655  INFO 25213 --- [nio-8888-exec-3] com.mediocre.util.BizUtils               : response status -> HTTP/1.1 400 Bad Request
     * 2021-08-23 21:41:03.656  INFO 25213 --- [nio-8888-exec-3] com.mediocre.util.BizUtils               : response content -> {"errors":["1 分钟内只能发布 3 篇博文，请稍候发布，联系邮箱：contact@cnblogs.com"],"type":0}
     * @param postJsonStr
     * @return
     */
    @Override
    public String createOrUpdate(String postJsonStr) {
        // create eg. {"id":null,"postType":1,"accessPermission":0,"title":"aaa","url":null,"postBody":"ccc","categoryIds":[1356051],"inSiteCandidate":false,"inSiteHome":false,"siteCategoryId":null,"blogTeamIds":null,"isPublished":true,"displayOnHomePage":true,"isAllowComments":true,"includeInMainSyndication":true,"isPinned":false,"isOnlyForRegisterUser":false,"isUpdateDateAdded":false,"entryName":null,"description":null,"featuredImage":null,"tags":["linux","idea"],"password":null,"datePublished":"2021-08-17T10:33:05.850Z","isMarkdown":true,"isDraft":true,"autoDesc":null,"changePostType":false,"blogId":0,"author":null,"removeScript":false,"clientInfo":null,"changeCreatedTime":false,"canChangeCreatedTime":false}
        // update eg. {"id":15153570,"postType":1,"accessPermission":0,"title":"problems_java","url":"//www.cnblogs.com/mediocreWorld/p/15153570.html","postBody":"[TOC]\n\n# problems_java\n\n## 1 tomcat运行javaweb项目报错\nerorlog: \n```java\njava.lang.UnsupportedClassVersionError: ... : Unsupported major.minor version 52.0\n```\nRCA:   \n使用高版本的JDK编译的Java class文件试图在较低版本的JVM上运行。jdk高版本能兼容低版本，但是低版本不能兼容高版本。我的项目使用jdk1.8在eclipse编译并运行，然后放到服务器上的jdk为1.7的tomcat中运行，所以报错了。  \n注：stanford parser和jdk版本对应关系：  \n```\nJ2SE 8 = 52,\nJ2SE 7 = 51,\nJ2SE 6.0 = 50,\nJ2SE 5.0 = 49,\nJDK 1.4 = 48,\nJDK 1.3 = 47,\nJDK 1.2 = 46,\nJDK 1.1 = 45\n```\nsolution:  \n修改eclipse配置，然后重新编译导出war包，放到服务器上运行，具体配置如下：  \n1. eclipse中右击项目，点击“Properties”；  \n2. 进入Java Compiler，右侧的Complier Compliance level设为1.7；  \n3. 进入Project Facets，右侧的Java设置为1.7（此项也可以不改，未验证过）；  \n4. 进入Java Build Path——Libraries，JRE System Library改为jdk1.7（此项也可以不改，亲测），保证旁边的Order and Export选项卡的JRE System Library的jdk版本与之相同；  \n5. 如果上述还不管用的话试试这个，其实上面的步骤做完，相当于做了这一步，效果完全相同：  \n打开项目所在的文件夹，打开.settings文件夹，修改里面的`org.eclipse.jdt.core.prefs`和\n`org.eclipse.wst.common.project.facet.core.xml`文件，将所有是1.8的地方修改为1.7  \n\n参考链接：https://www.cnblogs.com/jpfss/p/9036645.html  \n\n## 2 前端发起请求报错，响应码500\nerrorlog: \n```java\no.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [ResultDTO(code=2, message=Could not write JSON: -; nested exception is com.fasterxml.jackson.databin (truncated)...]\nm.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: -; nested exception is com.fasterxml.jackson.databind.JsonMappingException: - (through reference chain: ResultDTO[\"data\"]->java.util.ArrayList[1]->LaborCostInfoDTO[\"qn\"])]\n```\n\nRCA: \n这是jackson的一个bug，当实体类中的某个属性值为 - （英文的中横线）时，报以上错误。\n\nsolution: \n`-` 改为 `—`（中文的中横线）。\n\n## 3 \n","categoryIds":[],"inSiteCandidate":false,"inSiteHome":false,"siteCategoryId":null,"blogTeamIds":[],"isPublished":true,"displayOnHomePage":true,"isAllowComments":true,"includeInMainSyndication":true,"isPinned":false,"isOnlyForRegisterUser":false,"isUpdateDateAdded":false,"entryName":null,"description":"","featuredImage":null,"tags":[],"password":null,"datePublished":"2021-08-17T10:12:00.000Z","isMarkdown":true,"isDraft":false,"autoDesc":"problems_java 1 tomcat运行javaweb项目报错 erorlog: java.lang.UnsupportedClassVersionError: ... : Unsupported major.minor version 52.0 RCA: 使用高版本的JDK编译的Java ","changePostType":false,"blogId":409007,"author":"mediocrep","removeScript":false,"clientInfo":null,"changeCreatedTime":false,"canChangeCreatedTime":false}
        if (postJsonStr.contains("\"id\":null"))
            log.info("this is a creating operation!");
        else
            log.info("this is an updating operation!");
//        if (!StringUtils.hasText(id)) return null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        try {
            // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
            httpClient = HttpClientBuilder.create().build();
            // assemble url
            // eg. https://i.cnblogs.com/api/posts/15155337
            StringBuilder url = new StringBuilder(host).append(createOrUpdateUri);
            log.info("url === {}", url);
            // create request
            HttpPost httpPost = new HttpPost(url.toString());
            httpPost.setEntity(new StringEntity(postJsonStr, StandardCharsets.UTF_8));
            // 配置信息
            BizUtils.configRequest(httpPost);
            // 由客户端执行(发送)请求
            httpResponse = httpClient.execute(httpPost);
            // 获取并返回响应内容
            // eg. create response: {"id":15165266,"title":"bbb","url":"//www.cnblogs.com/mediocreWorld/p/15165266.html","blogUrl":"//www.cnblogs.com/mediocreWorld/","postType":1,"dateAdded":"2021-08-20T10:24:18.0195062+08:00","entryName":null}
            // eg. update response: {"id":15165266,"title":"bbb_update","url":"//www.cnblogs.com/mediocreWorld/p/15165266.html","blogUrl":"//www.cnblogs.com/mediocreWorld/","postType":1,"dateAdded":"2021-08-20T10:24:00","entryName":null}
            // eg. {"id":15177867,"title":"problems_halo","url":"//www.cnblogs.com/mediocreWorld/15177867.html","blogUrl":"//www.cnblogs.com/mediocreWorld/","postType":0,"dateAdded":"2021-08-23T21:40:40.0452915+08:00","entryName":null}
            return BizUtils.getResponseStr(httpResponse);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // close resources
            BizUtils.closeResources(httpResponse, httpClient);
        }
        return null;
    }

    @Override
    public String deletePerm(String id) {
        if (!StringUtils.hasText(id)) return null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        try {
            // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
            httpClient = HttpClientBuilder.create().build();
            // assemble url
            // eg. https://i.cnblogs.com/api/posts/15155337
            StringBuilder url = new StringBuilder(host).append(deletePermUri).append("?p=").append(id);
            log.info("url === {}", url);
            // create request
            HttpDelete httpDelete = new HttpDelete(url.toString());
            // 配置信息
            BizUtils.configRequest(httpDelete);
            // 由客户端执行(发送)请求
            httpResponse = httpClient.execute(httpDelete);
            // 获取并返回响应内容
            return BizUtils.getResponseStr(httpResponse);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // close resources
            BizUtils.closeResources(httpResponse, httpClient);
        }
        return null;
    }
}
